As technology advances, the demand for high speed digital computers increases to meet the need for both computational and data processing applications. The speed at which a given task can be performed by a central processing unit (CPU) depends upon numerous factors, two of the most important being the execution speed of the central processing unit and the program language implemented therein. While the execution speed is a function of cost factors and the state of art in the device technology, the programming language is generally a factor which can be tailored to increase both the speed of programming for a given task and also the speed of execution. The optimal programming language is assembly language which translates assembly code into machine language and, if the particular application permits its use, is the most efficient. Most programming languages, however, convert a source language into a target language through the use of a compiler. To produce an efficient code, the compilers are normally complex and require a large amount of memory which is seldom available on the small micro or minicomputers. To this end, various languages have been developed to improve programming efficiency without utilizing large compilers. One such language type is generally classified under the title "Threaded Interpretive Languages". Threaded intrepretive languages execute faster than other high level languages and are only between 20% to 75% slower than equivalent assembly language programs. In addition, threaded intrepretive languages provide a very compact compiled code which require less memory than equivalent assembly language programs. These languages are discussed in R. G. Loeliger, Threaded Interpretive Languages, 1981, and Leo Brodie, Starting Forth, 1981.
A threaded interpretive language utilizes an interpreter that accepts the source language and executes it directly without first producing a target language. A threaded code interpreter first translates the source language to an intermediate language or internal form and then executes the internal form. The internal form consists of a list of addresses of previously defined internal forms. This list is threaded together or compiled and then each of these addresses or internal forms is consecutively executed. To aid in the efficiency of interpretation, threaded interpretive languages resort to a series of stacks that operate in reverse polish notation; that is, the order in which expressions are to be evaluated is specified. For example, the numbers, identifiers or operands appear in the same order as they are to be applied.
A threaded interpretive language generally utilizes two stacks, a data stack and a return stack, both of which are last-in first-out push-down stacks. The data stack is utilized to store numbers and addresses of operands and the return stack is utilized to store program flow control parameters. During utilization of a threaded interpretive language, a plurality of program steps must be executed for each task that is performed. Normally, the list of addresses for the internal forms is referred to as secondary code bodies or "secondaries" and the internal form to be executed by the interpreter is referred to as a "primitive", which is a code body consisting of machine code that implements the desired action. Each thread of a threaded list terminates as a primitive and then returns to thread through the secondaries once more to execute another primitive. Each time a primitive is executed, addresses of a given secondary must be stored and, once the primitive is executed, retrieved to return to the proper location in the program. Obviously, the most efficient type of programming application is one which executes a series of primitives without threading through a large number of secondaries. This type of program will execute at essentially the speed of an assembly language program.
For a given programming application with threaded interpretive languages using conventional microprocessors, a finite number of clock cycles are required to execute the machine code that makes up a given primitive. For example, in a threaded interpretive language implemented on a microprocessor based system utilizing a Z80 microprocessor manufactured by Intel Corp., a primitive for duplicating the top element in the data stack would require approximately 32 timing states of the microprocessor. In the performance of another primitive, the Z80 microprocessor based system would require approximately 10 timing states to discard the top stack item. Since the primitive is the most efficient level of operation for a threaded interpretive language, execution at the primitive level constitutes the efficiency limit of a programming language. Therefore, there exists a need for an alternate technique to increase efficiency by executing portions of the programs at a faster rate and/or executing the primitives at a highly increased rate.